/**
 * 
 */
package com.lehecai.core.service.impl.memcached;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.utils.AddrUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lehecai.core.exception.MemcachedConnectionTimeoutException;
import com.lehecai.core.exception.MemcachedOperationTimeoutException;
import com.lehecai.core.memcached.IMemcachedObject;
import com.lehecai.core.memcached.MemcachedConfig;
import com.lehecai.core.service.memcached.MemcachedService;

/**
 * xmemcached客户端实现
 * @author leiming
 *
 */
public class XMemcachedServiceImpl implements MemcachedService {
	
	protected final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
	
	private MemcachedConfig memcachedConfig;
	
	protected MemcachedClient getConnection() throws Exception {
		try {
			MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(memcachedConfig.getHostname()+":"+memcachedConfig.getPort()));
			MemcachedClient mc = builder.build();
			return mc;
		} catch (IOException e) {
			logger.error("连接MC出错", e);
			throw new MemcachedConnectionTimeoutException("连接MC出错");
		}
	}
	
	protected void disconnect(MemcachedClient mc) throws Exception {
		if (mc != null && mc.isShutdown()) {
			mc.shutdown();
		}
	}

	@Override
	public boolean delete(String key) throws Exception {
		MemcachedClient mc = this.getConnection();
		
		try {
			return mc.delete(key);
		} catch (TimeoutException e) {
			logger.error("请求超时", e);
			throw new MemcachedOperationTimeoutException(e.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		} finally {
			this.disconnect(mc);
		}
	}

	/* (non-Javadoc)
	 * @see com.lehecai.core.service.memcached.MemcachedService#get(java.lang.String)
	 */
	@Override
	public IMemcachedObject get(String key) throws Exception {
		try {
			return get(key, memcachedConfig.getTimeout());
		} catch (TimeoutException e) {
			logger.error("请求超时", e);
			throw new MemcachedOperationTimeoutException(e.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		}
	}

	@Override
	public IMemcachedObject get(String key, long timeout) throws Exception {
		MemcachedClient mc = this.getConnection();
		
		try {
			IMemcachedObject obj = mc.get(key, (timeout*1000) );
			return obj;
		} catch (InterruptedException e) {
			logger.error(e.getMessage(), e);
			throw e;
		} catch (TimeoutException e) {
			logger.error("请求超时", e);
			throw new MemcachedOperationTimeoutException(e.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		} finally {
			this.disconnect(mc);
		}
	}

	@Override
	public boolean set(String key, IMemcachedObject object, int alive,
			long timeout) throws Exception {
		MemcachedClient mc = this.getConnection();
		
		try {
			return mc.set(key, alive, object, (timeout * 1000) );
		} catch (InterruptedException e) {
			logger.error(e.getMessage(), e);
			throw e;
		} catch (TimeoutException e) {
			logger.error("请求超时", e);
			throw new MemcachedOperationTimeoutException(e.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		} finally {
			this.disconnect(mc);
		}
	}

	@Override
	public Map<String, IMemcachedObject> mget(Collection<String> keys) throws Exception {
		return mget(keys, memcachedConfig.getTimeout());
	}

	@Override
	public Map<String, IMemcachedObject> mget(Collection<String> keys,
			long timeout) throws Exception {
		MemcachedClient mc = this.getConnection();
		
		try {
			Map<String, IMemcachedObject> result = mc.get(keys, (timeout * 1000) );
			return result;
		} catch (InterruptedException e) {
			logger.error(e.getMessage(), e);
			throw e;
		} catch (TimeoutException e) {
			logger.error("请求超时", e);
			throw new MemcachedOperationTimeoutException(e.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw e;
		} finally {
			this.disconnect(mc);
		}
	}

	@Override
	public boolean set(String key, IMemcachedObject object, int alive) throws Exception {
		return this.set(key, object, alive, memcachedConfig.getTimeout());
	}

	public MemcachedConfig getMemcachedConfig() {
		return memcachedConfig;
	}

	public void setMemcachedConfig(MemcachedConfig memcachedConfig) {
		this.memcachedConfig = memcachedConfig;
	}

}
